#include "wds_enemy_manager.h"
#include "wds_enemy_collection.h"
#include "wds_bullet.h"

#include "num/rand.h"
#include "lang/lang.h"
#include "util/mmgr.h"		    // Needs to come in early
#include "util/common_macros.h"		// macros
#include "util/log.h"		    // logging
#include "util/timer.h"		    // logging

WDSEnemyManager::WDSEnemyManager()
{
	m_EnemyShadow.Create("char/shadow.png");
	
}

WDSEnemyManager::~WDSEnemyManager()
{
	Clear();
}

WDSEnemyManager&		WDSEnemyManager::Instance()
{
	static WDSEnemyManager Inst;
	return Inst;
}


void		WDSEnemyManager::RenderDecal(const math::Vec2& Offset,float Scale)
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		WDSEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		pEnemyCollecction->RenderDecal(Offset,Scale); 
	}
}

void		WDSEnemyManager::RenderDead(const math::Vec2& Offset,float Scale)
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		WDSEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		pEnemyCollecction->RenderDead(Offset,Scale); 		
	} 
}

void		WDSEnemyManager::Render(const math::Vec2& Offset,float Scale)
{
    
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		WDSEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		pEnemyCollecction->Render(Offset,Scale); 		
	} 
	
}

void		WDSEnemyManager::RenderShadow(const math::Vec2& Offset,float Scale)
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		WDSEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		pEnemyCollecction->RenderShadow(Offset,Scale); 		
	} 
}


void		WDSEnemyManager::Tick(float dt, float GameDifficulty, float PlayerReflex, const math::Vec2& Offset)
{
	if(m_FreezeCounter > 0)
	{
		m_FreezeCounter -= dt;
		return;
	}

	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		WDSEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		pEnemyCollecction->Tick(dt, GameDifficulty, PlayerReflex, Offset);
	}

}


void		WDSEnemyManager::Clear()
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		WDSEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		pEnemyCollecction->Clear();
	}

	for( int i = (int)m_EnemyCollections.size() - 1; i >= 0; i--)
	{
		WDSEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		UTIL_SAFE_DELETE(pEnemyCollecction);
	}
	m_EnemyCollections.resize(0);
}


void		WDSEnemyManager::Spawn(WDSEnemy::ENEMY_TYPES EnemyType, 
								   WDSEnemy::ENEMY_SPAWN_TYPE SpawnType,
								   const math::Vec2& Offset)
{
	bool Found = false;
	for( int i = (int)m_EnemyCollections.size()- 1 ; i >= 0 ; i--)
	{
		WDSEnemyCollection* pEnemyCollection = m_EnemyCollections[i];

		if ( (int)pEnemyCollection->GetType() == EnemyType)
		{
			//if(!bUniqe)
			pEnemyCollection->Spawn(EnemyType, SpawnType, Offset);
			
			i = -1;
			Found = true;
		}		
	}

	if(!Found)
	{
		WDSEnemyCollection* pEnemyCollection = new WDSEnemyCollection(
													EnemyType,
													1 //pEnemyInfo->NameCRC
													);
		m_EnemyCollections.push_back(pEnemyCollection);
		pEnemyCollection->Spawn(EnemyType, SpawnType, Offset);
	}
	
}


int			WDSEnemyManager::GetCount()const
{
	int TotalCount = 0;
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		WDSEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		TotalCount += pEnemyCollecction->GetCount();
	}

	return TotalCount;
	
}



bool		WDSEnemyManager::HitTest(WDSBullet* pBullet)
{
	bool ReturnV = false;
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		WDSEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		if(pEnemyCollecction->HitTest(pBullet))
		{
			if(pBullet && pBullet->GetIsTypeGauss())
				ReturnV = true;
			else
				return true;
		}
	}

	return ReturnV;
}

WDSLifeObject*			WDSEnemyManager::GetRocketSeekerTarget(WDSBullet* pBullet)
{
	std::vector<WDSLifeObject*> pObjs;	
	WDSLifeObject* pReturnObj = NULL;
		

	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		WDSEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		
		for( int j = 0; j < pEnemyCollecction->GetCount(); j++)
		{
			WDSLifeObject* pObj = pEnemyCollecction->GetEnemyByIndex(j);
		
			if(pObj->IsAlive() && pObj->IsInsideScreen() )
			{
				pObjs.push_back(pObj);
			}
		}
	}
	if(pObjs.size() > 0)
	{
		int Index = num::RAND32::Instance().RandInt(0,pObjs.size()-1);
		pReturnObj = pObjs[Index];		
	}

	pObjs.resize(0);
	return pReturnObj;

}


void	WDSEnemyManager::DoDamangeToAll(float DamageAmount)
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		WDSEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		
		for( int j = 0; j < pEnemyCollecction->GetCount(); j++)
		{
			WDSLifeObject* pCraft = pEnemyCollecction->GetEnemyByIndex(j);
		
			if(pCraft->IsAlive() && pCraft->IsInsideScreen() )
			{
				//pCraft->GotDamage(DamageAmount,NULL, true);
			}
		}
	}
}



void	WDSEnemyManager::ForceKillAll()
{
	for(unsigned int i = 0; i < m_EnemyCollections.size(); i++)
	{
		WDSEnemyCollection* pEnemyCollecction= m_EnemyCollections[i];
		
		for( int j = 0; j < pEnemyCollecction->GetCount(); j++)
		{
			WDSLifeObject* pCraft = pEnemyCollecction->GetEnemyByIndex(j);		
			pCraft->ForceKill();
		}
	}	
}

void	WDSEnemyManager::Freeze()
{
	const float MAX_COUNTER = 10.0f;
	m_FreezeCounter = MAX_COUNTER;
}

void	WDSEnemyManager::RenderShadowInPos(const math::Vec2& Pos, 
									float Rotation,
									const math::Vec2& Offset, 
									float Scale)
{
	m_EnemyShadow.m_Pos = Pos - Offset;
	m_EnemyShadow.m_Rotation = Rotation;
	m_EnemyShadow.m_Size = m_EnemyShadow.m_SizeOriginal * Scale;
	m_EnemyShadow.RenderRotated();
}